package com.usefullc.system.service.component.risk;

import com.usefullc.common.constants.CacheConstants;
import com.usefullc.common.constants.SystemConstant;
import com.usefullc.common.enums.RiskCheckConditionResType;
import com.usefullc.common.exception.BizException;
import com.usefullc.common.util.JsonUtil;
import com.usefullc.system.service.AbstractService;
import com.usefullc.system.service.component.SystemConfigComponent;
import com.usefullc.system.service.interceptor.AspectProcess;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * 风控验证处理 （后续模块化，目前基于AuthRes 的表达式简单进行）
 * 范围包括（个人，公共）
 * 处理方式（验证，拒绝服务）
 * 验证方式（包括但不限于验证码，短信，指纹，google auth,人脸）
 * @author: Sampson
 * @date: 2022-06-19 15:31
 */
@Component
public class RiskCheckAspectProcess extends AbstractService implements AspectProcess {

    @Autowired
    private RequestResComponent authComponent;

    @Autowired
    private RedisTemplate redisTemplate;

//    @Autowired
//    private ImgCodeComponent imgCodeComponent;

    @Autowired
    private SystemConfigComponent systemConfigComponent;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;



    @Override
    public void process(ProceedingJoinPoint joinPoint, HttpServletRequest request) {
        Map<String, RequestResource> riskUrlAuthResMap = authComponent.getRiskUrlAuthResMap();
        String requestURI = request.getRequestURI();
        if (!riskUrlAuthResMap.containsKey(requestURI)) {
            return;
        }
        RequestResource authResObj = riskUrlAuthResMap.get(requestURI);
        String riskCheckCondition = authResObj.getRiskCheckCondition();
        ArrayList<RiskCheckCondition> riskCheckConditionList = JsonUtil.json2ArrayList(riskCheckCondition, RiskCheckCondition.class);
        if (CollectionUtils.isEmpty(riskCheckConditionList)) {
            return;
        }
        boolean needCheck = false;
        Integer checkType = RiskCheckConditionResType.RANDOM_CODE.getCode();
        String deviceId = request.getHeader(SystemConstant.DEVICE_ID);
        String key = "risk_"+deviceId+"_"+requestURI;
        for (RiskCheckCondition riskCheckConditionObj : riskCheckConditionList) {
            //只要满足一条就处理返回
            //条件参数判断
            Integer timeSecond = riskCheckConditionObj.getTimeSecond();
            Integer count = riskCheckConditionObj.getCount();
            long timeSecondEnd = System.currentTimeMillis() / 1000;
            long timeSecondStart = timeSecondEnd - timeSecond;
            Long calcCount = redisTemplate.opsForZSet().count(key, timeSecondStart, timeSecondEnd);
            if(calcCount >= count){  //命中
                needCheck = true;
                checkType = riskCheckConditionObj.getResType();
                break;
            }
        }
        //记录条件参数
        long timeSecond = System.currentTimeMillis() / 1000;
        redisTemplate.opsForZSet().incrementScore(key,timeSecond,timeSecond);
        //end


        if (needCheck) {
            if(checkType == RiskCheckConditionResType.REJECT.getCode()){  //拒绝
                throw new BizException(SystemConstant.ResponseCode.SYSTEM_ERROR,"服务拒绝");
            }

            //获取前端提交的数据
            String codeParam = null;
            Object[] args = joinPoint.getArgs();
            if(args != null && args.length > 0){
                if(StringUtils.equalsIgnoreCase("application/json",request.getHeader("Content-type"))){
                    Object arg = args[0];
                    String jsonParam = JsonUtil.bean2Json(arg);
                    HashMap<String, String> paramMap = JsonUtil.json2Map(jsonParam);
                    codeParam = paramMap.get(SystemConstant.CHECK_CODE);
                }
            }
            //end
            if(StringUtils.isNotEmpty(codeParam)){
                if(checkType == RiskCheckConditionResType.RANDOM_CODE.getCode()){  //随机验证码

                    String appName = systemConfigComponent.getAppName();
//                    UserTypeEnum userType = UserTypeEnum.getByEnName(appName);
                    String checkCodeKey = StringUtils.join(new Object[]{CacheConstants.RISK_RANDOM_CODE, deviceId}, "_");

                    String cacheCheckCode = stringRedisTemplate.opsForValue().get(checkCodeKey);
                    if (StringUtils.isEmpty(cacheCheckCode)) {
                        throw new BizException("验证码已失效，请重新获取",false);
                    }
                    if (!StringUtils.equals(cacheCheckCode, codeParam)) {
                        throw new BizException("验证码错误，请重新输入",false);
                    }

                }else if(checkType == RiskCheckConditionResType.SMS.getCode()){  //短信

                }
                //验证通过，返回
                return;
            }
            //需要验证开启
            throw new BizException(SystemConstant.ResponseCode.CODE_CHECK,"开启验证");
        }
    }

    @Override
    public void clean() {

    }
}
